﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Clipping.Infrastructure.Models;
using System.IO;
using System.Xml.Linq;
namespace Clipping.Utils
{
    public class UserInfoProvider
    {

        private static UserInfoProvider instance = new UserInfoProvider();

        private string path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data", "UserInfo.xml");

        private bool userInfoReady = false;
        private DateTime lastModifyTime = default(DateTime);
        private List<UserInfo> allUserInfos;
        private Dictionary<string, UserInfo> userInfoDic;



        public static UserInfoProvider GetInstance()
        {
            return instance;
        }

        public bool IsClientInfoDownloaded()
        {
            return File.Exists(path);
        }


        public List<UserInfo> GetAllUserInfos()
        {
            if (!userInfoReady)
                tryReadUserInfo();
            return this.allUserInfos;
        }

        private void tryReadUserInfo()
        {
            if (System.IO.File.Exists(path))
            {
                this.lastModifyTime = System.IO.File.GetLastWriteTime(path);
                string fileContent = System.IO.File.ReadAllText(path, Encoding.UTF8);
                this.allUserInfos = parse(fileContent);
                this.userInfoDic = new Dictionary<string, UserInfo>();
                foreach (var ui in this.allUserInfos)
                {
                    if (this.userInfoDic.ContainsKey(ui.UserName))
                    {
                    }
                    else 
                    {
                        this.userInfoDic[ui.UserName] = ui;
                    }
                }
            }
        }

        private List<UserInfo> parse(string fileContent)
        {
            List<UserInfo> rtn = new List<UserInfo>();
            int i = fileContent.IndexOf("<");
            if (i != 0)
                fileContent = fileContent.Substring(i);
            XDocument xDoc = XDocument.Parse(fileContent, LoadOptions.None);
            var userNodes = xDoc.Descendants("Users").First().Descendants("User");
            foreach (var userNode in userNodes)
            {
                UserInfo userInfo = Parse(userNode);
                rtn.Add(userInfo);
            }
            return rtn;
        }

        private UserInfo Parse(XElement userNode)
        {
            UserInfo rtn = new UserInfo();
            rtn.UserId = ReadValueStr(userNode, "Id");
            rtn.UserName = ReadValueStr(userNode, "Name");
            string clientIds= ReadValueStr(userNode, "ClientId");
            if (!string.IsNullOrEmpty(clientIds))
            {
                rtn.clientIds = clientIds.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            }
            else
                rtn.clientIds = new List<string>() {"*" };
            return rtn;
        }
        protected static string ReadValueStr(XElement node, string propertyName)
        {
            if (node.Attribute(propertyName) != null)
            {
                var rtn = node.Attribute(propertyName).Value;
                if (!string.IsNullOrEmpty(rtn))
                    return rtn.Trim();
                return null;
            }
            else
            {
                return null;
            }
        }

        public Dictionary<string, UserInfo> GetAllUserInfoDic()
        {
            if (!userInfoReady)
                tryReadUserInfo();
            return this.userInfoDic;
        }


        public UserInfo TryGetUserInfoByName(string username)
        {
            if (string.IsNullOrEmpty(username))
                return null;
            if (!userInfoReady)
                tryReadUserInfo();
           
            if (this.userInfoDic != null)
            {
                UserInfo rtn;
                this.userInfoDic.TryGetValue(username, out rtn);
                return rtn;
            }
            else
            {
                return null;
            }

        }

    }
}
